package cn.edu.sjtu.stap.sdg;

import java.io.*;
import java.util.Iterator;
import java.util.Map;

import org.aspectj.org.eclipse.jdt.internal.compiler.ast.*;

import cn.edu.sjtu.stap.cfg.*;
import cn.edu.sjtu.stap.cg.*;
import cn.edu.sjtu.stap.sdg.SystemDependenceGraph;

public class SDGResultOutput {
    private static PrintStream output = null;

    private static SDGResultOutput instance = null;

    public static SDGResultOutput getInstance() {
        if (instance == null) {
            instance = new SDGResultOutput();
        }
        return instance;
    }

    public static PrintStream getSystemOutputStream() {
        return output = System.out;
    }

    public static PrintStream getFileOutputStream(String fileName) {
        try {
            output = new PrintStream(new FileOutputStream(fileName + ".txt"));
            return output;
        } catch (Exception e) {
//            System.err.println(e);
            e.printStackTrace();
            return System.out;
        }
    }

    public void writeCgs(final PrintStream output,
            final Map<ASTNode, CallGraph> cgs) {
        Iterator<ASTNode> i = cgs.keySet().iterator();
        while (i.hasNext()) {
            ASTNode node = i.next();
            CallGraph g = cgs.get(node);
            output.println("------------------------------");
            output.println("The method is:");
            output.println(node);
            output.println("The call graph is:");
             output.println(g);
            output.println();
        }
    }

    public void writeSdg(final PrintStream output,
            final Map<AbstractMethodDeclaration, SystemDependenceGraph> sdgs) {
        if (sdgs == null) {
            output.println("The SDG graph is: null");
            return;
        }
        Iterator<AbstractMethodDeclaration> i = sdgs.keySet().iterator();
        while (i.hasNext()) {
            ASTNode node = i.next();
            SystemDependenceGraph g = sdgs.get(node);
            output.println("------------------------------");
            output.println("The method is:");
            output.println(node);
            output.println("The SDG graph is:");
            output.println(g);
            output.println();
        }
    }

    public void writeIntraproceduralCfg(final PrintStream output,
            final Map<AbstractMethodDeclaration, ControlFlowGraph> cfgs) {
        Iterator<AbstractMethodDeclaration> i = cfgs.keySet().iterator();
        while (i.hasNext()) {
            AbstractMethodDeclaration method = i.next();
            ControlFlowGraph g = cfgs.get(method);
            output.println("---------------------------------------");
            output.println("The method is:");
            output.println(method);
            output.println();
            output.println("Its Intra-CFG is:");
            output.println(g);
            output.println();
        }
    }

    public void writeInterproceduralCfg(final PrintStream output,
            final Map<AbstractMethodDeclaration, ControlFlowGraph> cfgs) {
        Iterator<AbstractMethodDeclaration> i = cfgs.keySet().iterator();
        while (i.hasNext()) {
            AbstractMethodDeclaration method = i.next();
            ControlFlowGraph g = cfgs.get(method);
            output.println();
            output.println("CFG: ----------------------------------");
            output.println("The program entry is:");
            output.println(method);
            output.println();
            output.println("Size of node set: " + g.getSizeOfNodes());
            output.println("Size of edge set: " + g.getSizeOfEdges());
            output.println("The whole CFG is:");
            output.println(g);
            output.println();
        }
    }

    public static void close() {
        try {
            if (output != System.out) {
                output.close();
            }
        } catch (Exception e) {
//            System.err.println(e);
        }
    }
}
